home *** CD-ROM | disk | FTP | other *** search
/ CU Amiga Super CD-ROM 6 / CU Amiga Magazine's Super CD-ROM 06 (1996)(EMAP Images)(GB)(Track 1 of 4)[!][issue 1997-01].iso / cucd / prog / gnu-c / manualbrowser / main.c < prev    next >
C/C++ Source or Header  |  1994-12-07  |  15KB  |  630 lines

  1. /************************************************************************/
  2. /*                                                                      */
  3. /*  Copyright (C) 1994  Christian Stieber                               */
  4. /*                                                                      */
  5. /* This program is free software; you can redistribute it and/or modify */
  6. /* it under the terms of the GNU General Public License as published by */
  7. /* the Free Software Foundation; either version 2 of the License, or    */
  8. /* (at your option) any later version.                                  */
  9. /*                                                                      */
  10. /* This program is distributed in the hope that it will be useful,      */
  11. /* but WITHOUT ANY WARRANTY; without even the implied warranty of       */
  12. /* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the        */
  13. /* GNU General Public License for more details.                         */
  14. /*                                                                      */
  15. /* You should have received a copy of the GNU General Public License    */
  16. /* along with this program; if not, write to the Free Software          */
  17. /* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.            */
  18. /*                                                                      */
  19. /************************************************************************/
  20. /*                                                                      */
  21. /* Author address:                                                      */
  22. /*   Christian Stieber                                                  */
  23. /*   Konradstraße 41                                                    */
  24. /*   D-85055 Ingolstadt                                                 */
  25. /*   (Germany)                                                          */
  26. /*   Phone: 0841-59896                                                  */
  27. /*                                                                      */
  28. /************************************************************************/
  29.  
  30. #ifndef V39
  31. #define CreatePool LibCreatePool
  32. #define DeletePool LibDeletePool
  33. #define AllocPooled LibAllocPooled
  34. #define FreePooled LibFreePooled
  35. #endif
  36.  
  37. #ifndef DOS_DOSEXTENS_H
  38. #include <dos/dosextens.h>
  39. #endif
  40.  
  41. #ifndef DOS_EXALL_H
  42. #include <dos/exall.h>
  43. #endif
  44.  
  45. #ifndef INTUITION_INTUITION_H
  46. #include <intuition/intuition.h>
  47. #endif
  48.  
  49. #ifndef LIBRARIES_AMIGAGUIDE_H
  50. #include <libraries/amigaguide.h>
  51. #endif
  52.  
  53. #ifndef WORKBENCH_STARTUP_H
  54. #include <workbench/startup.h>
  55. #endif
  56.  
  57. #ifndef WORKBENCH_WORKBENCH_H
  58. #include <workbench/workbench.h>
  59. #endif
  60.  
  61. #ifndef __GNUC__
  62. #ifndef CLIB_EXEC_PROTOS_H
  63. #include <clib/exec_protos.h>
  64. #endif
  65.  
  66. #ifndef CLIB_DOS_PROTOS_H
  67. #include <clib/dos_protos.h>
  68. #endif
  69.  
  70. #ifndef CLIB_UTILITY_PROTOS_H
  71. #include <clib/utility_protos.h>
  72. #endif
  73.  
  74. #ifndef CLIB_INTUITION_PROTOS_H
  75. #include <clib/intuition_protos.h>
  76. #endif
  77.  
  78. #ifndef CLIB_ICON_PROTOS_H
  79. #include <clib/icon_protos.h>
  80. #endif
  81.  
  82. #ifndef CLIB_AMIGAGUIDE_PROTOS_H
  83. #include <clib/amigaguide_protos.h>
  84. #endif
  85.  
  86. #include <pragmas/exec_pragmas.h>
  87. #include <pragmas/dos_pragmas.h>
  88. #include <pragmas/intuition_pragmas.h>
  89. #include <pragmas/utility_pragmas.h>
  90. #include <pragmas/icon_pragmas.h>
  91. #include <pragmas/amigaguide_pragmas.h>
  92. #endif
  93.  
  94. #include <string.h>
  95.  
  96. #include "Globals.h"
  97.  
  98. /***********************************************/
  99.  
  100. struct DosLibrary *DOSBase;
  101. struct IntuitionBase *IntuitionBase;
  102. struct Library *AmigaGuideBase;
  103. struct Library *UtilityBase;
  104.  
  105. /***********************************************/
  106.  
  107. #ifdef __GNUC__
  108.  
  109. #include "Inlines.h"
  110.  
  111. #ifndef V39
  112. APTR AllocPooled (APTR, ULONG);
  113. void FreePooled (APTR, APTR, ULONG);
  114. APTR CreatePool (ULONG, ULONG, ULONG);
  115. void DeletePool (APTR);
  116. #endif
  117.  
  118. #endif /* __GNUC__ */
  119.  
  120. /***********************************************/
  121.  
  122. #define CONFIGFILE    "ManualBrowser.config"
  123.  
  124. /***********************************************/
  125.  
  126. char Version[] = "$VER: ManualBrowser " PROGVERSION " (" PROGDATE ")"
  127. #ifdef V39
  128. "(V39) "
  129. #endif
  130. "(" CPU ") "
  131. "© 1994 Christian Stieber";
  132.  
  133. /***********************************************/
  134.  
  135. #define BASENAME   "ManBrowser"
  136. #define PUDDLESIZE (20*1024)
  137.  
  138. /***********************************************/
  139.  
  140. struct ActionNode *ActionList;
  141. BPTR ManDir;
  142. long LineLength = 70;
  143. char DatabaseName[64];
  144.  
  145. /***********************************************/
  146.  
  147. static void *MemoryPool;
  148.  
  149. static AMIGAGUIDEHOST AmigaGuideHostHandle;
  150. static AMIGAGUIDECONTEXT AmigaGuideHandle;
  151.  
  152. static char Filename[64];
  153.  
  154. static BPTR FileHandle;
  155.  
  156. static struct WBStartup *WBStartupMessage;
  157.  
  158. static struct EasyStruct EasyStruct =
  159. {
  160.   5 * 4,
  161.   0,
  162.   "Manual browser " PROGVERSION " error",
  163.   NULL,
  164.   NULL
  165. };
  166.  
  167. /***********************************************/
  168.  
  169. #ifdef __GNUC__
  170. static void 
  171. MyExit (int) __attribute__ ((noreturn));
  172. #endif
  173.  
  174.      static void MyExit (int RC)
  175.  
  176. {
  177.   if (WBStartupMessage)
  178.     {
  179.       Forbid ();
  180.       ReplyMsg ((struct Message *) WBStartupMessage);
  181.     }
  182.   exit (RC);
  183. }
  184.  
  185. /************************************************************************/
  186. /*                                                                      */
  187. /* Malloc()                                                             */
  188. /*                                                                      */
  189. /************************************************************************/
  190.  
  191. void *
  192. Malloc (ULONG Size)
  193.  
  194. {
  195.   ULONG *Memory;
  196.  
  197.   Size += 4;
  198.   if (Memory = AllocPooled (MemoryPool, Size))
  199.     {
  200.       *Memory = Size;
  201.       Memory++;
  202.     }
  203.   return Memory;
  204. }
  205.  
  206. /************************************************************************/
  207. /*                                                                      */
  208. /* Free()                                                               */
  209. /*                                                                      */
  210. /************************************************************************/
  211.  
  212. void 
  213. Free (void *Memory)
  214.  
  215. {
  216.   if (Memory)
  217.     {
  218.       FreePooled (MemoryPool, ((ULONG *) Memory) - 1, *(((ULONG *) Memory) - 1));
  219.     }
  220. }
  221.  
  222. /***********************************************/
  223.  
  224. static void 
  225. DisplayError (char *Format,...)
  226.  
  227. {
  228.   if (WBStartupMessage)
  229.     {
  230.       EasyStruct.es_TextFormat = Format;
  231.       EasyStruct.es_GadgetFormat = "Quit";
  232.       EasyRequestArgs (NULL, &EasyStruct, NULL, (&Format) + 1);
  233.     }
  234.   else
  235.     {
  236.       VPrintf (Format, (&Format) + 1);
  237.       PutStr ("\n");
  238.     }
  239. }
  240.  
  241. /***********************************************/
  242.  
  243. static void 
  244. DisplayDosError (char *Filename)
  245.  
  246. {
  247.   if (WBStartupMessage)
  248.     {
  249.       char Buffer[256];
  250.       char *t;
  251.  
  252.       t = Buffer;
  253.       Fault (IoErr (), Filename, t, sizeof (Buffer));
  254.       EasyStruct.es_TextFormat = "%s";
  255.       EasyStruct.es_GadgetFormat = "Quit";
  256.       EasyRequestArgs (NULL, &EasyStruct, NULL, &t);
  257.     }
  258.   else
  259.     {
  260.       PrintFault (IoErr (), Filename);
  261.     }
  262. }
  263.  
  264. /***********************************************/
  265.  
  266. #ifdef __GNUC__
  267. static void 
  268. CloseAll (int) __attribute__ ((noreturn));
  269. #endif
  270.  
  271.      static void CloseAll (int RC)
  272.  
  273. {
  274.   if (AmigaGuideHandle)
  275.     CloseAmigaGuide (AmigaGuideHandle);
  276.   if (AmigaGuideHostHandle)
  277.     {
  278.       while (RemoveAmigaGuideHostA (AmigaGuideHostHandle, NULL))
  279.     {
  280.       Delay (TICKS_PER_SECOND);
  281.     }
  282.     }
  283.   if (FileHandle)
  284.     {
  285.       DeleteFile (Filename);
  286.     }
  287.   if (ManDir)
  288.     UnLock (ManDir);
  289.   if (MemoryPool)
  290.     DeletePool (MemoryPool);
  291.   CloseLibrary (AmigaGuideBase);
  292.   CloseLibrary (UtilityBase);
  293.   CloseLibrary ((struct Library *) IntuitionBase);
  294.   CloseLibrary ((struct Library *) DOSBase);
  295.   MyExit (RC);
  296. }
  297.  
  298. /***********************************************/
  299.  
  300. static void 
  301. InitThings (void)
  302.  
  303. {
  304.   struct Process *MyProcess;
  305.  
  306.   MyProcess = (struct Process *) FindTask (NULL);
  307.   if (MyProcess->pr_CLI)
  308.     {
  309.       WBStartupMessage = NULL;
  310.     }
  311.   else
  312.     {
  313.       do
  314.     {
  315.       WaitPort (&MyProcess->pr_MsgPort);
  316.     }
  317.       while (!(WBStartupMessage = (struct WBStartup *) GetMsg (&MyProcess->pr_MsgPort)));
  318.     }
  319.  
  320. #ifdef V39
  321.   if (!(DOSBase = (struct DosLibrary *) OpenLibrary ("dos.library", 39)))
  322. #else
  323.   if (!(DOSBase = (struct DosLibrary *) OpenLibrary ("dos.library", 37)))
  324. #endif
  325.     {
  326.       MyExit (100);
  327.     }
  328.  
  329.   if (!(IntuitionBase = (struct IntuitionBase *) OpenLibrary ("intuition.library", 37)))
  330.     {
  331.       CloseLibrary ((struct Library *) DOSBase);
  332.       MyExit (100);
  333.     }
  334.  
  335.   if (!(UtilityBase = OpenLibrary ("utility.library", 37)))
  336.     {
  337.       DisplayError ("Unable to open utility.library V37");
  338.       CloseAll (RETURN_FAIL);
  339.     }
  340.  
  341.   if (!(AmigaGuideBase = OpenLibrary ("amigaguide.library", 34)))
  342.     {
  343.       DisplayError ("Unable to open amigaguide.library V34");
  344.       CloseAll (RETURN_FAIL);
  345.     }
  346.  
  347.   if (!(MemoryPool = CreatePool (0, PUDDLESIZE, PUDDLESIZE)))
  348.     {
  349.       DisplayError ("Unable to create memory pool");
  350.       CloseAll (RETURN_FAIL);
  351.     }
  352. }
  353.  
  354. /***********************************************/
  355.  
  356. static void 
  357. AddDatabase (void)
  358.  
  359. {
  360. #ifdef __GNUC__
  361.   static struct Hook AmigaGuideHook =
  362.   {
  363.     {NULL, NULL},
  364.     HookEntryA1,
  365.     AmigaGuideHostDispatcher,
  366.     NULL
  367.   };
  368. #else
  369.   static struct Hook AmigaGuideHook =
  370.   {
  371.     {NULL, NULL},
  372.     AmigaGuideHostDispatcher,
  373.     NULL,
  374.     NULL
  375.   };
  376. #endif
  377.  
  378.   char *t;
  379.  
  380.   Sprintf (DatabaseName, BASENAME ".%lx", FindTask (NULL));
  381.   Sprintf (Filename, "t:%s.guide", DatabaseName);
  382.  
  383.   if (!(FileHandle = Open (Filename, MODE_NEWFILE)))
  384.     {
  385.       DisplayDosError (Filename);
  386.       CloseAll (RETURN_ERROR);
  387.     }
  388.   t = DatabaseName;
  389.   if (VFPrintf (FileHandle, "@database %s.guide\n"
  390.         "@node EnItSiRhC\n"
  391.         "@endnode\n", &t) == -1)
  392.     {
  393.       DisplayDosError (Filename);
  394.       Close (FileHandle);
  395.       CloseAll (RETURN_ERROR);
  396.     }
  397.   Close (FileHandle);
  398.  
  399.   if (!(AmigaGuideHostHandle = AddAmigaGuideHostA (&AmigaGuideHook, DatabaseName, NULL)))
  400.     {
  401.       DisplayError ("Unable to add dynamic amiga guide host");
  402.       CloseAll (RETURN_FAIL);
  403.     }
  404. }
  405.  
  406. /***********************************************/
  407.  
  408. static void 
  409. OpenDatabase (void)
  410.  
  411. {
  412.   struct NewAmigaGuide NewAmigaGuide;
  413.  
  414.   NewAmigaGuide.nag_Lock = NULL;
  415.   NewAmigaGuide.nag_Name = Filename;
  416.   NewAmigaGuide.nag_Screen = NULL;
  417.   NewAmigaGuide.nag_PubScreen = NULL;
  418.   NewAmigaGuide.nag_HostPort = NULL;
  419.   NewAmigaGuide.nag_ClientPort = BASENAME;
  420.   NewAmigaGuide.nag_BaseName = BASENAME;
  421.   NewAmigaGuide.nag_Flags = HTF_NOACTIVATE;
  422.   NewAmigaGuide.nag_Context = NULL;
  423.   NewAmigaGuide.nag_Node = NULL;
  424.   NewAmigaGuide.nag_Line = 0;
  425.   NewAmigaGuide.nag_Extens = NULL;
  426.   NewAmigaGuide.nag_Client = NULL;
  427.  
  428.   if (!(AmigaGuideHandle = OpenAmigaGuideA (&NewAmigaGuide, NULL)))
  429.     {
  430.       DisplayError ("Unable to open amiga guide database");
  431.       CloseAll (RETURN_FAIL);
  432.     }
  433. }
  434.  
  435. /***********************************************/
  436.  
  437. #ifdef __GNUC__
  438. #define ICONBASE IconBase,
  439. #else
  440. #define ICONBASE
  441. #endif
  442.  
  443. static void 
  444. GetParams (void)
  445.  
  446. {
  447.   if (WBStartupMessage)
  448.     {
  449.       struct Library *IconBase;
  450.  
  451.       if ((IconBase = OpenLibrary ("icon.library", 33)))
  452.     {
  453.       if (WBStartupMessage->sm_NumArgs)
  454.         {
  455.           BPTR OldCurrDir;
  456.           struct DiskObject *DiskObject;
  457.           OldCurrDir = CurrentDir (WBStartupMessage->sm_ArgList[0].wa_Lock);
  458.           if ((DiskObject = GetDiskObject (ICONBASE WBStartupMessage->sm_ArgList[0].wa_Name)))
  459.         {
  460.           char *ManPath;
  461.           if (!((ManPath = FindToolType (ICONBASE (UBYTE **) DiskObject->do_ToolTypes, "MANUALDIR")) ||
  462.             (ManPath = FindToolType (ICONBASE (UBYTE **) DiskObject->do_ToolTypes, "MANDIR")) ||
  463.             (ManPath = FindToolType (ICONBASE (UBYTE **) DiskObject->do_ToolTypes, "DIR"))))
  464.             {
  465.               ManPath = "man:";
  466.             }
  467.           if (!(ManDir = Lock (ManPath, SHARED_LOCK)))
  468.             {
  469.               DisplayDosError (ManPath);
  470.             }
  471.           FreeDiskObject (ICONBASE DiskObject);
  472.         }
  473.           CurrentDir (OldCurrDir);
  474.         }
  475.       CloseLibrary (IconBase);
  476.     }
  477.     }
  478.   else
  479.     {
  480.       struct
  481.       {
  482.     char *ManualDir;
  483.       }
  484.       Arguments;
  485.  
  486.       struct RDArgs *RDArgs;
  487.  
  488.       Arguments.ManualDir = "man:";
  489.       if (!(RDArgs = ReadArgs ("MANUALDIR=MANDIR=DIR", (long *) &Arguments, NULL)))
  490.     {
  491.       PrintFault (IoErr (), NULL);
  492.       CloseAll (RETURN_FAIL);
  493.     }
  494.       if (!(ManDir = Lock (Arguments.ManualDir, SHARED_LOCK)))
  495.     {
  496.       DisplayDosError (Arguments.ManualDir);
  497.     }
  498.       FreeArgs (RDArgs);
  499.     }
  500.   if (!ManDir)
  501.     {
  502.       CloseAll (RETURN_FAIL);
  503.     }
  504. }
  505.  
  506. /***********************************************/
  507.  
  508. int 
  509. ReadConfigFile (BPTR ConfigFile, struct ActionNode **ActionList)
  510.  
  511. {
  512.   BPTR OldInput;
  513.  
  514.   OldInput = SelectInput (ConfigFile);
  515.   while (TRUE)
  516.     {
  517.       struct
  518.     {
  519.       char *Pattern;
  520.       char *Action;
  521.     }
  522.       CurrentLine;
  523.       struct RDArgs *LineArgs;
  524.  
  525.       while (TRUE)
  526.     {
  527.       int Character;
  528.  
  529.       Character = FGetC (ConfigFile);
  530.       if (Character != '\n' && Character != ' ' && Character != '\t')
  531.         {
  532.           if (Character == -1)
  533.         {
  534.           if (IoErr ())
  535.             {
  536.               return FALSE;
  537.             }
  538.           SelectInput (OldInput);
  539.           return TRUE;
  540.         }
  541.           UnGetC (ConfigFile, Character);
  542.           break;
  543.         }
  544.     }
  545.       CurrentLine.Pattern = NULL;
  546.       CurrentLine.Action = NULL;
  547.       if (LineArgs = ReadArgs ("P/A,A/A/F", (long *) &CurrentLine, NULL))
  548.     {
  549.       struct ActionNode *ActionNode;
  550.       int AllocSize, PatternSize;
  551.       PatternSize = 2 * strlen (CurrentLine.Pattern);
  552.       AllocSize = sizeof (struct ActionNode) + strlen (CurrentLine.Action) + PatternSize;
  553.       if ((ActionNode = Malloc (AllocSize)))
  554.         {
  555.           ActionNode->Pattern = Stpcpy (ActionNode->Action, CurrentLine.Action) + 1;
  556.           if (ParsePatternNoCase (CurrentLine.Pattern, ActionNode->Pattern, PatternSize) != -1)
  557.         {
  558.           ActionNode->Next = *ActionList;
  559.           *ActionList = ActionNode;
  560.         }
  561.           else
  562.         {
  563.           DisplayError ("Error in pattern: %s", CurrentLine.Pattern);
  564.           ActionNode = NULL;
  565.         }
  566.         }
  567.       FreeArgs (LineArgs);
  568.       if (!ActionNode)
  569.         {
  570.           return FALSE;
  571.         }
  572.     }
  573.       else
  574.     {
  575.       return FALSE;
  576.     }
  577.     }
  578.   /* Not reached */
  579. }
  580.  
  581. /***********************************************/
  582.  
  583. static void 
  584. ReadConfig (void)
  585.  
  586. {
  587.   static char *ConfigFile[] =
  588.   {
  589.     "PROGDIR:" CONFIGFILE,
  590.     "S:" CONFIGFILE,
  591.     "ENV:" CONFIGFILE
  592.   };
  593.  
  594.   int i;
  595.  
  596.   for (i = 0; i < 3; i++)
  597.     {
  598.       BPTR FileHandle;
  599.       if ((FileHandle = Open (ConfigFile[i], MODE_OLDFILE)))
  600.     {
  601.       int Result;
  602.  
  603.       Result = ReadConfigFile (FileHandle, &ActionList);
  604.       Close (FileHandle);
  605.       if (!Result)
  606.         {
  607.           DisplayDosError (ConfigFile[i]);
  608.           CloseAll (RETURN_FAIL);
  609.         }
  610.     }
  611.     }
  612. }
  613.  
  614. /***********************************************/
  615.  
  616. void Main (void);
  617.  
  618. void 
  619. Main (void)
  620.  
  621. {
  622.   InitThings ();
  623.   GetParams ();
  624.   ReadConfig ();
  625.   AddDatabase ();
  626.   OpenDatabase ();
  627.   CloseAll (RETURN_OK);
  628.   /* Not reached */
  629. }
  630.